iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
Rust

Rust 後端入門系列 第 6

Day 6 Vec、HashMap 與疊代器

  • 分享至 

  • xImage
  •  

今天這篇文章,我將介紹Rust中兩個相當有用的資料結構:Vec以及HashMap,Vec可以用來儲存一組數字或是用戶的資訊,而HashMap可以在常數時間複雜度內,快速查詢儲存在其中的內容。

另外,還要傳授如何使用疊代器優雅處理內容。

Vec

Vec是Rust常見的資料結構之一,可以把Vec想像成一個清單,可以不斷的將內容插入其中。

用一個範例,讓大家熟悉Vec吧。

範例

如何建立一個Vec,有三種方式:

fn main() {
    // 第一種,建立空Vec,之後加入內容
    let mut shopping_list: Vec<&str> = Vec::new();
    shopping_list.push("蛋糕");
    shopping_list.push("小餅乾");
    
    // 第二種,使用Vec!,儲存設定的內容
    let numbers = vec![1, 2, 3, 4, 5];
    
    // 第三種,使用Vec!,儲存重複的內容
    // 底下的方式可以建立用10個0的Vec,這樣就不用打一堆0
    let zeros = vec![0; 10];
    
    // 顯示Vec的內容
    println!("購物清單:{:?}", shopping_list);
    println!("數字:{:?}", numbers);
    println!("十個零:{:?}", zeros);
}

使用時機

  • 有順序的內容:當順序很重要的時候(例如:排行榜)
  • 資料量有可能變動時,例如:隨時可能要加入一筆資料,導致無法確定長度。

安全取得Vec其中一筆資料的方式

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    
    // 危險的方式,如果超過範圍會發生panic(程式錯誤,終止)
    println!("{:?}",numbers[1]);
    
    // 安全的方式,嘗試取得範圍外的內容,會顯示超出陣列範圍,然後繼續執行後面的程式
    if let Some(value) = numbers.get(1) {
	    println!("取得Vec元素: {}", value);
    } else {
	    println!("超出陣列範圍");
    }
}

HashMap

HashMap就像是一本字典,可以快速在字典裡根據詞(HashMap的Key)找到對應的解釋(HashMap的Key對應的內容)。

接下來,開始建立第一個HashMap吧。

範例

use std::collections::HashMap;

fn main() {
    // 第一個方法:各別插入
    let mut scores = HashMap::new();
    scores.insert("Alan", 10);
    scores.insert("Dan", 9);
    println!("分數表:{:?}", scores);
    
    // 第二個方法:直接建立
    let config = HashMap::from([
        ("host", "localhost"),
        ("port", "8080"),
    ]);
    println!("設定:{:?}", config);
}

使用時機

  • 快速查詢:可以使用O(1)查詢HashMap其中的內容
  • 去除重複的資料:重複插入相同鍵值時,只留下最後的資料

疊代器

疊代器用來處理數據,就像是工廠的流水線,將送來的東西一個個做相同的處理。

Map

Map可以把每個元素轉換成你希望的模樣。

下面是Map搭配Vec的使用教學,將未稅的甜甜價轉換成含稅的價格:

fn main() {
    let prices = vec![100, 200, 300];
    let with_tax: Vec<f64> = prices
        .iter()// 使用疊代器
        .map(|price| *price as f64 * 1.05) // 從prices取得實際的數值後,轉換成f64,再乘1.05
        .collect();// 啟動計算,並將計算後的數值收集起來
    println!("含稅價格:{:?}", with_tax);
}

什麼時候可以使用Map

  • 當需要更改某些數據的資料格式時,例如:把字串轉換成數字
  • 需要對數字進行操作時,例如:計算折扣價、含稅價
  • 其他需要對全部的元素做統一的處理時

Filter

Filter就像一個篩子,只允許滿足特定條件的元素通過。

底下是一個購物網站中的篩選範例,我們將進行篩選後,顯示符合條件的商品:

#[derive(Debug)]
struct Product {
    name: String,
    price: i32,
    in_stock: bool,
}

fn main() {
    let products = vec![
        Product { name: "筆電".to_string(), price: 30000, in_stock: true },
        Product { name: "滑鼠".to_string(), price: 1000, in_stock: false },
        Product { name: "鍵盤".to_string(), price: 2000, in_stock: true },
        Product { name: "螢幕".to_string(), price: 8000, in_stock: true },
    ];
    
    // 顯示有庫存(in_stock是true)並且價格小於10000的商品
    let filter_result: Vec<&Product> = products
        .iter()
        .filter(|p| p.in_stock && p.price < 10000)
        .collect();
    
    println!("符合條件的商品:");
    for product in filter_result {
        println!("  - {} : (${:})", product.name, product.price);
    }
}

哪些時候應該使用Filter

  • 需要找出符合條件的元素
  • 想要排除不需要的元素

Collect

我們在Map和Filter的部分都見到過Collect,可以說有iter的地方最後都會有collect做結尾。collect負責將iter處理後的內容收集起來,放入對應的元素中。



上一篇
Day 5 Rust錯誤處理: Option 與 Result
下一篇
Day 7 用 Clap 框架完成第一個 Rust 專案:待辦事項管理器
系列文
Rust 後端入門13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言